home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Archive-tools / UnZip 2.0 / UnZip 2.0 Docs / UnZip 2.0 Docs.rsrc / TEXT_130.txt < prev    next >
Text File  |  1992-09-27  |  25KB  |  1,083 lines

  1. The Unshrinking and Unreducing C source code of Samuel H. Smith was used in UnZip 2.0. The full version 1.2 of Samuel H. Smith‚Äôs code from the file ST_UNZIP.ZIP follows:
  2.  
  3.  
  4. #define ATARI_ST 1
  5.  
  6. /*
  7.  * Copyright 1989 Samuel H. Smith;  All rights reserved
  8.  *
  9.  * Do not distribute modified versions without my permission.
  10.  * Do not remove or alter this notice or any other copyright notice.
  11.  * If you use this in your own program you must distribute source code.
  12.  * Do not use any of this in a commercial product.
  13.  *
  14.  */
  15.  
  16. /*
  17.  * UnZip - A simple zipfile extract utility
  18.  *
  19.  * To compile:
  20.  *      tcc -B -O -Z -G -mc unzip.c        ;turbo C 2.0, compact model
  21.  *
  22.  */
  23.  
  24. #define CODE_VERSION  "UnZip:  Zipfile Extract v1.2 of 03-15-89;  (C) 1989 Samuel H. Smith"
  25. #define PRG_VERSION   "\
  26. UnZip:  Atari ST Zipfile Extract v1.2 of 03-30-89\n\
  27. Ported to the Atari ST by Darin Wayrynen.\n\
  28. Derived from code Copyrighted (c)1989 by S.H.Smith"
  29.  
  30. typedef unsigned char byte;    /* code assumes UNSIGNED bytes */
  31. typedef long longint;
  32. typedef unsigned word;
  33. typedef char boolean;
  34.  
  35. #define STRSIZ 256
  36.  
  37. #include <stdio.h>
  38.  /* this is your standard header for all C compiles */
  39.  
  40. #ifndef ATARI_ST
  41. #include <stdlib.h>
  42.  /* this include defines various standard library prototypes */
  43. #else
  44. long buffer_size,in_size,out_size;
  45. #endif
  46.  
  47. /*
  48.  * SEE HOST OPERATING SYSTEM SPECIFICS SECTION STARTING NEAR LINE 180
  49.  *
  50.  */
  51.  
  52.  
  53. /* ----------------------------------------------------------- */
  54. /*
  55.  * Zipfile layout declarations
  56.  *
  57.  */
  58.  
  59. typedef longint signature_type;
  60.  
  61.  
  62. #define LOCAL_FILE_HEADER_SIGNATURE  0x04034b50L
  63.  
  64.  
  65. typedef struct local_file_header {
  66.     word version_needed_to_extract;
  67.     word general_purpose_bit_flag;
  68.     word compression_method;
  69.     word last_mod_file_time;
  70.     word last_mod_file_date;
  71.     longint crc32;
  72.     longint compressed_size;
  73.     longint uncompressed_size;
  74.     word filename_length;
  75.     word extra_field_length;
  76. } local_file_header;
  77.  
  78.  
  79. #define CENTRAL_FILE_HEADER_SIGNATURE  0x02014b50L
  80.  
  81.  
  82. typedef struct central_directory_file_header {
  83.     word version_made_by;
  84.     word version_needed_to_extract;
  85.     word general_purpose_bit_flag;
  86.     word compression_method;
  87.     word last_mod_file_time;
  88.     word last_mod_file_date;
  89.     longint crc32;
  90.     longint compressed_size;
  91.     longint uncompressed_size;
  92.     word filename_length;
  93.     word extra_field_length;
  94.     word file_comment_length;
  95.     word disk_number_start;
  96.     word internal_file_attributes;
  97.     longint external_file_attributes;
  98.     longint relative_offset_local_header;
  99. } central_directory_file_header;
  100.  
  101.  
  102. #define END_CENTRAL_DIR_SIGNATURE  0x06054b50L
  103.  
  104.  
  105. typedef struct end_central_dir_record {
  106.     word number_this_disk;
  107.     word number_disk_with_start_central_directory;
  108.     word total_entries_central_dir_on_this_disk;
  109.     word total_entries_central_dir;
  110.     longint size_central_directory;
  111.     longint offset_start_central_directory;
  112.     word zipfile_comment_length;
  113. } end_central_dir_record;
  114.  
  115.  
  116.  
  117. /* ----------------------------------------------------------- */
  118. /*
  119.  * input file variables
  120.  *
  121.  */
  122.  
  123. #define INBUFSIZ 0x2000L
  124. byte *inbuf;            /* input file buffer - any size is legal */
  125. byte *inptr;
  126.  
  127. int incnt;
  128. unsigned bitbuf;
  129. int bits_left;
  130. boolean zipeof;
  131.  
  132. int zipfd;
  133. char zipfn[STRSIZ];
  134. local_file_header lrec;
  135.  
  136.  
  137. /* ----------------------------------------------------------- */
  138. /*
  139.  * output stream variables
  140.  *
  141.  */
  142.  
  143. #define OUTBUFSIZ 0x6000L
  144. byte *outbuf;                   /* buffer for rle look-back */
  145. byte *outptr;
  146.  
  147. longint outpos;            /* absolute position in outfile */
  148. int outcnt;            /* current position in outbuf */
  149.  
  150. int outfd;
  151. char filename[STRSIZ];
  152. char extra[STRSIZ];
  153.  
  154. #define DLE 144
  155.  
  156.  
  157. /* ----------------------------------------------------------- */
  158. /*
  159.  * shrink/reduce working storage
  160.  *
  161.  */
  162.  
  163. int factor;
  164. byte followers[256][64];
  165. byte Slen[256];
  166.  
  167. #define max_bits 13
  168. #define init_bits 9
  169. #define hsize 8192
  170. #define first_ent 257
  171. #define clear 256
  172.  
  173. typedef int hsize_array_integer[hsize+1];
  174. typedef byte hsize_array_byte[hsize+1];
  175.  
  176. hsize_array_integer prefix_of;
  177. hsize_array_byte suffix_of;
  178. hsize_array_byte stack;
  179.  
  180. int codesize;
  181. int maxcode;
  182. int free_ent;
  183. int maxcodemax;
  184. int offset;
  185. int sizex;
  186.  
  187.  
  188.  
  189. /* ============================================================= */
  190. /*
  191.  * Host operating system details
  192.  *
  193.  */
  194.  
  195. #ifndef ATARI_ST
  196. #include <string.h>
  197. #else
  198. #include <strings.h>
  199. #define strchr index
  200. #endif
  201.  /* this include defines strcpy, strcmp, etc. */
  202.  
  203. #ifndef ATARI_ST
  204. #include <io.h>
  205.  /*
  206.   * this include file defines
  207.   *             struct ftime ...        (* file time/date stamp info *)
  208.   *             int setftime (int handle, struct ftime *ftimep);
  209.   *             #define SEEK_CUR  1     (* lseek() modes *)
  210.   *             #define SEEK_END  2
  211.   *             #define SEEK_SET  0
  212.   */
  213. #else
  214. #define SEEK_CUR  1     (* lseek() modes *)
  215. #define SEEK_END  2
  216. #define SEEK_SET  0
  217. #endif
  218.  
  219.  
  220. #include <fcntl.h>
  221.  /*
  222.   * this include file defines
  223.   *             #define O_BINARY 0x8000  (* no cr-lf translation *)
  224.   * as used in the open() standard function
  225.   */
  226.  
  227. #ifndef ATARI_ST
  228. #include <sys/stat.h>
  229.  /*
  230.   * this include file defines
  231.   *             #define S_IREAD 0x0100  (* owner may read *)
  232.   *             #define S_IWRITE 0x0080 (* owner may write *)
  233.   * as used in the creat() standard function
  234.   */
  235. #endif
  236.  
  237. #ifdef ATARI_ST
  238. #define HIGH_LOW 1
  239. #include <osbind.h>
  240. typedef struct _dt {                    /* My creation! DAW */
  241.     unsigned realdate;
  242.     unsigned realtime;
  243. } dt;
  244. #endif
  245.  
  246.  /*
  247.   * change 'undef' to 'define' if your machine stores high order bytes in
  248.   * lower addresses.
  249.   */
  250.  
  251. #ifndef ATARI_ST
  252. void set_file_time()
  253.  /*
  254.   * set the output file date/time stamp according to information from the
  255.   * zipfile directory record for this file 
  256.   */
  257. {
  258.     union {
  259.                 dt ft;        /* system file time record */
  260.         struct {
  261.                         word ztime;     /* date and time words */
  262.                         word zdate;     /* .. same format as in .ZIP file */
  263.         } zt;
  264.     } td;
  265.  
  266.     /*
  267.      * set output file date and time - this is optional and can be
  268.      * deleted if your compiler does not easily support setftime() 
  269.      */
  270.  
  271.     td.zt.ztime = lrec.last_mod_file_time;
  272.     td.zt.zdate = lrec.last_mod_file_date;
  273.  
  274.     setftime(outfd, &td.ft);
  275. }
  276. #else
  277. #define set_file_time() ;
  278. #endif
  279.  
  280.  
  281. int create_output_file()
  282.  /* return non-0 if creat failed */
  283. {
  284.     /* create the output file with READ and WRITE permissions */
  285. #ifndef ATARI_ST
  286.     outfd = creat(filename, S_IWRITE | S_IREAD);
  287. #else
  288.     outfd = open(filename, O_CREAT | O_RDWR| O_BINARY);
  289. #endif
  290.     if (outfd < 1) {
  291.         printf("Can't create output: %s\n", filename);
  292.         return 1;
  293.     }
  294.  
  295.     /*
  296.      * close the newly created file and reopen it in BINARY mode to
  297.      * disable all CR/LF translations 
  298.      */
  299. #ifndef ATARI_ST
  300.     /*
  301.      * Not neccessary with Atari ST.  Just open() in Binary mode.
  302.      */
  303.     close(outfd);
  304.     outfd = open(filename, O_RDWR | O_BINARY);
  305. #endif
  306.  
  307.     /* write a single byte at EOF to pre-allocate the file */
  308.         lseek(outfd, lrec.uncompressed_size - 1L, SEEK_SET);
  309.     write(outfd, "?", 1);
  310.     lseek(outfd, 0L, SEEK_SET);
  311.     return 0;
  312. }
  313.  
  314.  
  315. int open_input_file()
  316.  /* return non-0 if creat failed */
  317. {
  318.     /*
  319.      * open the zipfile for reading and in BINARY mode to prevent cr/lf
  320.      * translation, which would corrupt the bitstreams 
  321.      */
  322.  
  323.     zipfd = open(zipfn, O_RDONLY | O_BINARY);
  324.     if (zipfd < 1) {
  325.         printf("Can't open input file: %s\n", zipfn);
  326.         return (1);
  327.     }
  328.     return 0;
  329. }
  330.  
  331.  
  332. #ifdef HIGH_LOW
  333.  
  334. void swap_bytes(wordp)
  335. word *wordp;
  336.  /* convert intel style 'short int' variable to host format */
  337. {
  338.     char *charp = (char *) wordp;
  339.     char temp;
  340.  
  341.     temp = charp[0];
  342.     charp[0] = charp[1];
  343.     charp[1] = temp;
  344. }
  345.  
  346. void swap_lbytes(longp)
  347. longint *longp;
  348.  /* convert intel style 'long' variable to host format */
  349. {
  350.     char *charp = (char *) longp;
  351.     char temp[4];
  352.  
  353.     temp[3] = charp[0];
  354.     temp[2] = charp[1];
  355.     temp[1] = charp[2];
  356.     temp[0] = charp[3];
  357.  
  358.     charp[0] = temp[0];
  359.     charp[1] = temp[1];
  360.     charp[2] = temp[2];
  361.     charp[3] = temp[3];
  362. }
  363.  
  364. #endif
  365.  
  366.  
  367.  
  368. /* ============================================================= */
  369.  
  370. int FillBuffer()
  371.  /* fill input buffer if possible */
  372. {
  373.     int readsize;
  374.  
  375.         if (lrec.compressed_size <= 0)
  376.         return incnt = 0;
  377.  
  378.         if (lrec.compressed_size > in_size)
  379.         readsize = in_size;
  380.     else
  381.                 readsize = (int) lrec.compressed_size;
  382.     incnt = read(zipfd, inbuf, readsize);
  383.  
  384.         lrec.compressed_size -= incnt;
  385.     inptr = inbuf;
  386.     return incnt--;
  387. }
  388.  
  389. int ReadByte(x)
  390. unsigned *x;
  391.  /* read a byte; return 8 if byte available, 0 if not */
  392. {
  393.     if (incnt-- == 0)
  394.         if (FillBuffer() == 0)
  395.             return 0;
  396.  
  397.     *x = *inptr++;
  398.     return 8;
  399. }
  400.  
  401.  
  402. /* ------------------------------------------------------------- */
  403. static unsigned mask_bits[] =
  404.         {0,     0x0001, 0x0003, 0x0007, 0x000f,
  405.                 0x001f, 0x003f, 0x007f, 0x00ff,
  406.                 0x01ff, 0x03ff, 0x07ff, 0x0fff,
  407.                 0x1fff, 0x3fff, 0x7fff, 0xffff
  408.         };
  409.  
  410.  
  411. int FillBitBuffer(bits)
  412. register int bits;
  413. {
  414.     /* get the bits that are left and read the next word */
  415.     unsigned temp;
  416.         register int result = bitbuf;
  417.     int sbits = bits_left;
  418.     bits -= bits_left;
  419.  
  420.     /* read next word of input */
  421.     bits_left = ReadByte(&bitbuf);
  422.     bits_left += ReadByte(&temp);
  423.     bitbuf |= (temp << 8);
  424.     if (bits_left == 0)
  425.         zipeof = 1;
  426.  
  427.     /* get the remaining bits */
  428.         result = result | (int) ((bitbuf & mask_bits[bits]) << sbits);
  429.         bitbuf >>= bits;
  430.         bits_left -= bits;
  431.         return result;
  432. }
  433.  
  434. #define READBIT(nbits,zdest) { if (nbits <= bits_left) { zdest = (int)(bitbuf & mask_bits[nbits]); bitbuf >>= nbits; bits_left -= nbits; } else zdest = FillBitBuffer(nbits);}
  435.  
  436. /*
  437.  * macro READBIT(nbits,zdest)
  438.  *  {
  439.  *      if (nbits <= bits_left) {
  440.  *          zdest = (int)(bitbuf & mask_bits[nbits]);
  441.  *          bitbuf >>= nbits;
  442.  *          bits_left -= nbits;
  443.  *      } else
  444.  *          zdest = FillBitBuffer(nbits);
  445.  *  }
  446.  *
  447.  */
  448.  
  449.  
  450. /* ------------------------------------------------------------- */
  451.  
  452. #include "crc32.h"
  453.  
  454.  
  455. /* ------------------------------------------------------------- */
  456.  
  457. void FlushOutput()
  458.  /* flush contents of output buffer */
  459. {
  460.     UpdateCRC(outbuf, outcnt);
  461.     write(outfd, outbuf, outcnt);
  462.     outpos += outcnt;
  463.     outcnt = 0;
  464.     outptr = outbuf;
  465. }
  466.  
  467. #define OUTB(intc) { *outptr++=intc; if (++outcnt==out_size) FlushOutput(); }
  468.  
  469. /*
  470.  *  macro OUTB(intc)
  471.  *  {
  472.  *      *outptr++=intc;
  473.  *      if (++outcnt==out_size)
  474.  *          FlushOutput();
  475.  *  }
  476.  *
  477.  */
  478.  
  479.  
  480. /* ----------------------------------------------------------- */
  481.  
  482. void LoadFollowers()
  483. {
  484.         register int x;
  485.         register int i;
  486.  
  487.     for (x = 255; x >= 0; x--) {
  488.                 READBIT(6,Slen[x]);
  489.         for (i = 0; i < Slen[x]; i++) {
  490.                         READBIT(8,followers[x][i]);
  491.         }
  492.     }
  493. }
  494.  
  495.  
  496. /* ----------------------------------------------------------- */
  497. /*
  498.  * The Reducing algorithm is actually a combination of two
  499.  * distinct algorithms.  The first algorithm compresses repeated
  500.  * byte sequences, and the second algorithm takes the compressed
  501.  * stream from the first algorithm and applies a probabilistic
  502.  * compression method.
  503.  */
  504.  
  505. int L_table[] = {0, 0x7f, 0x3f, 0x1f, 0x0f};
  506.  
  507. int D_shift[] = {0, 0x07, 0x06, 0x05, 0x04};
  508. int D_mask[]  = {0, 0x01, 0x03, 0x07, 0x0f};
  509.  
  510. int B_table[] = {8, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5,
  511.          5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
  512.          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  513.          6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
  514.          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  515.          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  516.          7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  517.          7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  518.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  519.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  520.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  521.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  522.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  523.          8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  524.          8, 8, 8, 8};
  525.  
  526. /* ----------------------------------------------------------- */
  527.  
  528. void unReduce()
  529.  /* expand probablisticly reduced data */
  530. {
  531.         register int lchar;
  532.         register int nchar;
  533.         int ExState;
  534.         register int V;
  535.         register int Len;
  536.  
  537.         factor = lrec.compression_method - 1;
  538.     ExState = 0;
  539.     lchar = 0;
  540.     LoadFollowers();
  541.  
  542.         while (((outpos + outcnt) < lrec.uncompressed_size) && (!zipeof)) {
  543.         if (Slen[lchar] == 0)
  544.                         READBIT(8,nchar)      /* ; */
  545.                 else
  546.         {
  547.                         READBIT(1,nchar);
  548.                         if (nchar != 0)
  549.                                 READBIT(8,nchar)      /* ; */
  550.                         else
  551.             {
  552.                                 int follower;
  553.                                 int bitsneeded = B_table[Slen[lchar]];
  554.                                 READBIT(bitsneeded,follower);
  555.                                 nchar = followers[lchar][follower];
  556.             }
  557.         }
  558.  
  559.         /* expand the resulting byte */
  560.         switch (ExState) {
  561.  
  562.         case 0:
  563.                         if (nchar != DLE)
  564.                                 OUTB(nchar) /*;*/
  565.             else
  566.                 ExState = 1;
  567.             break;
  568.  
  569.         case 1:
  570.                         if (nchar != 0) {
  571.                                 V = nchar;
  572.                 Len = V & L_table[factor];
  573.                 if (Len == L_table[factor])
  574.                     ExState = 2;
  575.                 else
  576.                     ExState = 3;
  577.             }
  578.             else {
  579.                                 OUTB(DLE);
  580.                 ExState = 0;
  581.             }
  582.             break;
  583.  
  584.                 case 2: {
  585.                                 Len += nchar;
  586.                 ExState = 3;
  587.             }
  588.             break;
  589.  
  590.                 case 3: {
  591.                 register int i = Len + 3;
  592.                 int offset = (((V >> D_shift[factor]) &
  593.                                           D_mask[factor]) << 8) + nchar + 1;
  594.                 longint op = outpos + outcnt - offset;
  595.  
  596.                 /* special case- before start of file */
  597.                 while ((op < 0L) && (i > 0)) {
  598.                     OUTB(0);
  599.                     op++;
  600.                     i--;
  601.                 }
  602.  
  603.                 /* normal copy of data from output buffer */
  604.                 {
  605.                     register int ix = (int) (op % out_size);
  606.  
  607.                                         /* do a block memory copy if possible */
  608.                                         if ( ((ix    +i) < out_size) &&
  609.                                              ((outcnt+i) < out_size) ) {
  610.                                                 memcpy(outptr,&outbuf[ix],i);
  611.                                                 outptr += i;
  612.                                                 outcnt += i;
  613.                                         }
  614.  
  615.                                         /* otherwise copy byte by byte */
  616.                                         else while (i--) {
  617.                                                 OUTB(outbuf[ix]);
  618.                                                 if (++ix >= out_size)
  619.                                                         ix = 0;
  620.                                         }
  621.                                 }
  622.  
  623.                 ExState = 0;
  624.             }
  625.             break;
  626.         }
  627.  
  628.                 /* store character for next iteration */
  629.                 lchar = nchar;
  630.         }
  631. }
  632.  
  633.  
  634. /* ------------------------------------------------------------- */
  635. /*
  636.  * Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm
  637.  * with partial clearing.
  638.  *
  639.  */
  640.  
  641. void partial_clear()
  642. {
  643.         register int pr;
  644.         register int cd;
  645.  
  646.     /* mark all nodes as potentially unused */
  647.     for (cd = first_ent; cd < free_ent; cd++)
  648.         prefix_of[cd] |= 0x8000;
  649.  
  650.     /* unmark those that are used by other nodes */
  651.     for (cd = first_ent; cd < free_ent; cd++) {
  652.         pr = prefix_of[cd] & 0x7fff;    /* reference to another node? */
  653.                 if (pr >= first_ent)            /* flag node as referenced */
  654.             prefix_of[pr] &= 0x7fff;
  655.     }
  656.  
  657.     /* clear the ones that are still marked */
  658.     for (cd = first_ent; cd < free_ent; cd++)
  659.         if ((prefix_of[cd] & 0x8000) != 0)
  660.             prefix_of[cd] = -1;
  661.  
  662.     /* find first cleared node as next free_ent */
  663.         cd = first_ent;
  664.         while ((cd < maxcodemax) && (prefix_of[cd] != -1))
  665.                 cd++;
  666.         free_ent = cd;
  667. }
  668.  
  669.  
  670. /* ------------------------------------------------------------- */
  671.  
  672. void unShrink()
  673. {
  674.         #define  GetCode(dest) READBIT(codesize,dest)
  675.  
  676.     register int code;
  677.     register int stackp;
  678.     int finchar;
  679.     int oldcode;
  680.     int incode;
  681.  
  682.  
  683.     /* decompress the file */
  684.     maxcodemax = 1 << max_bits;
  685.     codesize = init_bits;
  686.     maxcode = (1 << codesize) - 1;
  687.     free_ent = first_ent;
  688.     offset = 0;
  689.     sizex = 0;
  690.  
  691.     for (code = maxcodemax; code > 255; code--)
  692.         prefix_of[code] = -1;
  693.  
  694.     for (code = 255; code >= 0; code--) {
  695.         prefix_of[code] = 0;
  696.         suffix_of[code] = code;
  697.     }
  698.  
  699.     GetCode(oldcode);
  700.     if (zipeof)
  701.         return;
  702.     finchar = oldcode;
  703.  
  704.         OUTB(finchar);
  705.  
  706.         stackp = hsize;
  707.  
  708.     while (!zipeof) {
  709.         GetCode(code);
  710.         if (zipeof)
  711.             return;
  712.  
  713.         while (code == clear) {
  714.             GetCode(code);
  715.             switch (code) {
  716.  
  717.             case 1:{
  718.                     codesize++;
  719.                     if (codesize == max_bits)
  720.                         maxcode = maxcodemax;
  721.                     else
  722.                         maxcode = (1 << codesize) - 1;
  723.                 }
  724.                 break;
  725.  
  726.             case 2:
  727.                 partial_clear();
  728.                 break;
  729.             }
  730.  
  731.             GetCode(code);
  732.             if (zipeof)
  733.                 return;
  734.         }
  735.  
  736.  
  737.         /* special case for KwKwK string */
  738.         incode = code;
  739.         if (prefix_of[code] == -1) {
  740.                         stack[--stackp] = finchar;
  741.             code = oldcode;
  742.         }
  743.  
  744.  
  745.         /* generate output characters in reverse order */
  746.         while (code >= first_ent) {
  747.                         stack[--stackp] = suffix_of[code];
  748.             code = prefix_of[code];
  749.         }
  750.  
  751.         finchar = suffix_of[code];
  752.                 stack[--stackp] = finchar;
  753.  
  754.  
  755.                 /* and put them out in forward order, block copy */
  756.                 if ((hsize-stackp+outcnt) < out_size) {
  757.                         memcpy(outptr,&stack[stackp],hsize-stackp);
  758.                         outptr += hsize-stackp;
  759.                         outcnt += hsize-stackp;
  760.                         stackp = hsize;
  761.                 }
  762.  
  763.                 /* output byte by byte if we can't go by blocks */
  764.                 else while (stackp < hsize)
  765.                         OUTB(stack[stackp++]);
  766.  
  767.  
  768.         /* generate new entry */
  769.         code = free_ent;
  770.         if (code < maxcodemax) {
  771.             prefix_of[code] = oldcode;
  772.             suffix_of[code] = finchar;
  773.  
  774.             do
  775.                 code++;
  776.             while ((code < maxcodemax) && (prefix_of[code] != -1));
  777.  
  778.             free_ent = code;
  779.         }
  780.  
  781.         /* remember previous code */
  782.         oldcode = incode;
  783.     }
  784.  
  785. }
  786.  
  787.  
  788. /* ---------------------------------------------------------- */
  789.  
  790. void extract_member()
  791. {
  792.     unsigned b;
  793.  
  794.     bits_left = 0;
  795.     bitbuf = 0;
  796.     incnt = 0;
  797.     outpos = 0L;
  798.     outcnt = 0;
  799.     outptr = outbuf;
  800.     zipeof = 0;
  801.     crc32val = 0xFFFFFFFFL;
  802.  
  803.  
  804.     /* create the output file with READ and WRITE permissions */
  805.     if (create_output_file())
  806.         prg_exit(1);
  807.  
  808.         switch (lrec.compression_method) {
  809.  
  810.     case 0:        /* stored */
  811.         {
  812.             printf(" Extracting: %-12s ", filename);
  813.             while (ReadByte(&b))
  814.                 OUTB(b);
  815.         }
  816.         break;
  817.  
  818.         case 1: {
  819.             printf("UnShrinking: %-12s ", filename);
  820.             unShrink();
  821.         }
  822.         break;
  823.  
  824.     case 2:
  825.     case 3:
  826.     case 4:
  827.         case 5: {
  828.             printf("  Expanding: %-12s ", filename);
  829.             unReduce();
  830.         }
  831.         break;
  832.  
  833.     default:
  834.         printf("Unknown compression method.");
  835.     }
  836.  
  837.  
  838.     /* write the last partial buffer, if any */
  839.     if (outcnt > 0) {
  840.         UpdateCRC(outbuf, outcnt);
  841.         write(outfd, outbuf, outcnt);
  842.     }
  843.  
  844.     /* set output file date and time */
  845.     set_file_time();
  846.  
  847.     close(outfd);
  848.  
  849.     crc32val = -1 - crc32val;
  850. #ifdef HIGH_LOW
  851.     swap_lbytes(&lrec.crc32);
  852. #endif
  853.         if (crc32val != lrec.crc32)
  854.                 printf(" Bad CRC %08lx  (should be %08lx)", lrec.crc32, crc32val);
  855.  
  856.     printf("\n");
  857. }
  858.  
  859.  
  860. /* ---------------------------------------------------------- */
  861.  
  862. void get_string(len,s)
  863. int len;
  864. char *s;
  865. {
  866.     read(zipfd, s, len);
  867.     s[len] = 0;
  868. }
  869.  
  870.  
  871. /* ---------------------------------------------------------- */
  872.  
  873. void process_local_file_header()
  874. {
  875.     read(zipfd, &lrec, sizeof(lrec));
  876.  
  877. #ifdef HIGH_LOW
  878.     swap_bytes(&lrec.filename_length);
  879.     swap_bytes(&lrec.extra_field_length);
  880.     swap_lbytes(&lrec.compressed_size);
  881.     swap_lbytes(&lrec.uncompressed_size);
  882.     swap_bytes(&lrec.compression_method);
  883. #endif
  884.  
  885.     get_string(lrec.filename_length, filename);
  886.     get_string(lrec.extra_field_length, extra);
  887.     extract_member();
  888. }
  889.  
  890.  
  891. /* ---------------------------------------------------------- */
  892.  
  893. void process_central_file_header()
  894. {
  895.     central_directory_file_header rec;
  896.     char filename[STRSIZ];
  897.     char extra[STRSIZ];
  898.     char comment[STRSIZ];
  899.  
  900.     read(zipfd, &rec, sizeof(rec));
  901.  
  902. #ifdef HIGH_LOW
  903.     swap_bytes(&rec.filename_length);
  904.     swap_bytes(&rec.extra_field_length);
  905.     swap_bytes(&rec.file_comment_length);
  906. #endif
  907.  
  908.     get_string(rec.filename_length, filename);
  909.     get_string(rec.extra_field_length, extra);
  910.     get_string(rec.file_comment_length, comment);
  911. }
  912.  
  913.  
  914. /* ---------------------------------------------------------- */
  915.  
  916. void process_end_central_dir()
  917. {
  918.     end_central_dir_record rec;
  919.     char comment[STRSIZ];
  920.  
  921.     read(zipfd, &rec, sizeof(rec));
  922.  
  923. #ifdef HIGH_LOW
  924.     swap_bytes(&rec.zipfile_comment_length);
  925. #endif
  926.  
  927.     get_string(rec.zipfile_comment_length, comment);
  928. }
  929.  
  930.  
  931. /* ---------------------------------------------------------- */
  932.  
  933. void process_headers()
  934. {
  935.     longint sig;
  936.  
  937.     while (1) {
  938.         if (read(zipfd, &sig, sizeof(sig)) != sizeof(sig))
  939.             return;
  940.  
  941. #ifdef HIGH_LOW
  942.         swap_lbytes(&sig);
  943. #endif
  944.  
  945.                 if (sig == LOCAL_FILE_HEADER_SIGNATURE)
  946.             process_local_file_header();
  947.                 else if (sig == CENTRAL_FILE_HEADER_SIGNATURE)
  948.             process_central_file_header();
  949.                 else if (sig == END_CENTRAL_DIR_SIGNATURE) {
  950.             process_end_central_dir();
  951.             return;
  952.         }
  953.                 else {
  954.             printf("Invalid Zipfile Header\n");
  955.             return;
  956.         }
  957.     }
  958.  
  959. }
  960.  
  961.  
  962. /* ---------------------------------------------------------- */
  963.  
  964. void extract_zipfile()
  965. {
  966.     /*
  967.      * open the zipfile for reading and in BINARY mode to prevent cr/lf
  968.      * translation, which would corrupt the bitstreams 
  969.      */
  970.     
  971.     printf("Buffers - ");
  972.     printf("(input --> %7ld bytes) ",in_size);
  973.     printf("(output --> %7ld bytes)\n\n",out_size);
  974.  
  975.     if (open_input_file())
  976.         prg_exit(1);
  977.  
  978.     process_headers();
  979.  
  980.     close(zipfd);
  981. }
  982.  
  983.  
  984. /* ---------------------------------------------------------- */
  985. /*
  986.  * main program
  987.  *
  988.  */
  989.  
  990. void main(argc,argv)
  991. int argc;
  992. char **argv;
  993. {
  994. #ifdef ATARI_ST
  995.     int buffer_fail = 0;
  996. #endif
  997.  
  998.            printf("\n\n%s\n",PRG_VERSION); 
  999.            printf("Courtesy of:  Darin Wayrynen, S.H.Smith and\n              The Tool Shop BBS,  (602) 279-2673.\n"); 
  1000.     if (argc != 2)
  1001.     {
  1002.         printf("\nYou may copy and distribute this program freely, provided that:\n");
  1003.         printf("    1)   No fee is charged for such copying and distribution, and\n");
  1004.         printf("    2)   It is distributed ONLY in its original, unmodified state.\n\n");
  1005.         printf("If you wish to distribute a modified version of this program, you MUST\n");
  1006.         printf("include the source code.\n\n");
  1007.         printf("If you modify this program, we would appreciate a copy of the  new source\n");
  1008.         printf("code.  Samuel is holding the copyright on the source code, so please don't\n");
  1009.         printf("delete his  name from the program files or from the documentation.\n\n");
  1010.         printf("IN NO EVENT WILL WE BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING ANY LOST\n");
  1011.         printf("PROFITS, LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES\n");
  1012.         printf("ARISING OUT OF YOUR USE OR INABILITY TO USE THE PROGRAM, OR FOR ANY\n");
  1013.         printf("CLAIM BY ANY OTHER PARTY.\n\n");
  1014.         printf("Usage:  UnZip FILE[.zip]\n");
  1015. #ifdef ATARI_ST
  1016.         prg_exit(0);
  1017. #else
  1018.         exit(1);
  1019. #endif
  1020.     }
  1021.     printf("\n");
  1022.  
  1023.     /* .ZIP default if none provided by user */
  1024.     strcpy(zipfn, argv[1]);
  1025.     if (strchr(zipfn, '.') == NULL)
  1026.         strcat(zipfn, ".ZIP");
  1027.  
  1028. #ifdef ATARI_ST
  1029.     /* ST buffer allocation */
  1030.     buffer_size = Malloc(-1L)-10000L;              /* returns largest free block */
  1031.     if (buffer_size<(INBUFSIZ + OUTBUFSIZ))
  1032.         buffer_fail=1;
  1033.     in_size = (buffer_size-(INBUFSIZ + OUTBUFSIZ))/100L*55L+INBUFSIZ;
  1034.     out_size = (buffer_size-(INBUFSIZ + OUTBUFSIZ))/100L*35L+OUTBUFSIZ;
  1035.     inbuf = (byte *)Malloc(in_size);         /* 60% */
  1036.     outbuf = (byte *)Malloc(out_size);        /* 40% */
  1037.     if ((inbuf== NULL) || (outbuf == NULL) || buffer_fail)
  1038.     {
  1039.         printf("Can't allocate buffers!\n");
  1040.         prg_exit(1);
  1041.     }
  1042. #else
  1043.         /* allocate i/o buffers */
  1044.     inbuf = (byte *) (malloc(INBUFSIZ));
  1045.     outbuf = (byte *) (malloc(OUTBUFSIZ));
  1046.     if ((inbuf == NULL) || (outbuf == NULL)) {
  1047.         printf("Can't allocate buffers!\n");
  1048.         exit(1);
  1049.     }
  1050. #endif
  1051.         /* do the job... */
  1052.         extract_zipfile();
  1053. #ifdef ATARI_ST
  1054.     prg_exit(0);
  1055. #else
  1056.     exit(0);
  1057. #endif
  1058. }
  1059.  
  1060. prg_exit(value)
  1061. int value;
  1062. {
  1063.     setbuffer(stdout,0L);                         /* turn off printf
  1064.                                                    buffering */
  1065.     printf("\nPress any key to continue.");
  1066.     
  1067.     Bconin(2);                                    /* wait for keypress before
  1068.                                                    exiting, in case prg is
  1069.                                                    run from desktop */
  1070.     printf("\n");
  1071.     exit(value);
  1072. }
  1073.  
  1074. #ifdef ATARI_ST
  1075. memcpy(to,from,count)
  1076. register char *to,*from;
  1077. register unsigned int count;
  1078. {
  1079.     for(;count>0;--count,++to,++from)
  1080.         *to=*from;
  1081. }
  1082. #endif
  1083.